﻿using System;
using System.Drawing;
using System.Windows.Forms;
using DAPNet;
using ZedGraph;

namespace Benchmark
{
    public partial class ClickDetectionStatsViewForm : Form
    {
        static private Color DarkPink = Color.FromArgb(129, 0, 81);

        static private Color LightPink = Color.FromArgb(227, 102, 181);

        static private Color DarkOrange = Color.FromArgb(166, 70, 0);

        static private Color LightOrange = Color.FromArgb(255, 174, 115);

        static private Color DarkBlue = Color.FromArgb(0, 103, 92);

        static private Color LightBlue = Color.FromArgb(93, 207, 195);

        static private Color DarkGreen = Color.FromArgb(109, 156, 0);

        static private Color LightGreen = Color.FromArgb(207, 247, 111);


        static private Color SamplesCurveColor = DarkBlue;

        static private Color ClickingCurveColor = DarkPink;

        static private Color ClickedCurveColor = DarkOrange;

        static private Color DetectionCurveColor = LightOrange;

        static private Color PerfectDetectionCurveColor = LightBlue;

        static private Color PositiveSliceColor = DarkGreen;

        static private Color FalseSliceColor = DarkPink;

        static private Color MissedSliceColor = DarkOrange;

        static private Color NegativeSliceColor = DarkBlue;


        static private string PercentageFormat = "0.000%";

        static private string DoubleFormat = "0.000";

        static private double SliceDisplacement = 0.05;

        static private SymbolType ShownSymbol = SymbolType.Plus;

        static private SymbolType HiddenSymbol = SymbolType.None;


        private ClickDetectionStats stats;

        private LineItem samplesCurve;

        private LineItem clickingCurve;

        private LineItem clickedCurve;

        private LineItem detectionCurve;

        private LineItem perfectDetectionCurve;
        
        private PieItem positiveSlice;

        private PieItem falseSlice;

        private PieItem missedSlice;

        private PieItem negativeSlice;


        public ClickDetectionStatsViewForm(ClickDetectionStats statistics)
        {
            InitializeComponent();
            
            detectionGraph.ScrollDoneEvent += new ZedGraphControl.ScrollDoneHandler(detectionGraph_ScrollDoneEvent);
            detectionGraph.ZoomEvent += new ZedGraphControl.ZoomEventHandler(detectionGraph_ZoomEvent);
            
            this.stats = statistics;
        }

        private void ClickDetectionForm_Load(object sender, EventArgs e)
        {
            InicializeStats();
            InicializeDetection();
            InicializeDisplay();

            ResetDisplay(0, stats.Count - 1);
            ResetStats(0, stats.Count - 1);            
            ResetDetection(0, stats.Count - 1);
        }


        private void InicializeDisplay()
        {
            displayClickedCheckBox.Checked = true;
            displaySamplesCheckBox.Checked = true;
            displayClickingCheckBox.Checked = true;
        }

        private void InicializeStats()
        {
            statsGraph.GraphPane.Title.IsVisible = false;
            statsGraph.GraphPane.Legend.IsVisible = false;

            positiveSlice = statsGraph.GraphPane.AddPieSlice(0, PositiveSliceColor, SliceDisplacement, "Positive");
            falseSlice = statsGraph.GraphPane.AddPieSlice(0, FalseSliceColor, SliceDisplacement, "False");
            missedSlice = statsGraph.GraphPane.AddPieSlice(0, MissedSliceColor, SliceDisplacement, "Missed");
            negativeSlice = statsGraph.GraphPane.AddPieSlice(0, NegativeSliceColor, SliceDisplacement, "Negative");

            statsGraph.GraphPane.AxisChange();
        }

        private void InicializeDetection()
        {
            detectionGraph.GraphPane.Title.IsVisible = false;
            detectionGraph.IsEnableVPan = false;
            detectionGraph.IsEnableVZoom = false;    
            detectionGraph.GraphPane.XAxis.Title.Text = "Sample";
            detectionGraph.GraphPane.YAxis.Title.Text = "Ampitude";

            clickedCurve = AddSamplesCurve("Clicked", stats.Clicked, ClickedCurveColor);
            samplesCurve = AddSamplesCurve("Samples", stats.Samples, SamplesCurveColor);
            clickingCurve = AddSamplesCurve("Clicking", stats.Clicking, ClickingCurveColor);
            detectionCurve = AddDetectionCurve("Detection", stats.Detection, DAPNet.Sample.MaxValue, DAPNet.Sample.BaseValue, DetectionCurveColor);
            perfectDetectionCurve = AddDetectionCurve("Perfect detection", stats.PerfectDetection, DAPNet.Sample.MinValue, DAPNet.Sample.BaseValue, PerfectDetectionCurveColor);

            detectionGraph.GraphPane.AxisChange();
        }


        private void ResetDisplay(int startIndex, int endIndex)
        {
            startTextBox.Text = startIndex.ToString();
            endTextBox.Text = endIndex.ToString();

            displaySamplesSymbolsCheckBox.Enabled = displaySamplesCheckBox.Checked;
            displayClickingSymbolsCheckBox.Enabled = displayClickingCheckBox.Checked;
            displayClickedSymbolsCheckBox.Enabled = displayClickedCheckBox.Checked;

            displayGroupBox.Refresh();
        }

        private void ResetStats(int startIndex, int endIndex)
        {
            double missedRatio = stats.GetMissedPositiveRatio(startIndex, endIndex);
            missedTextBox.Text = missedRatio.ToString(PercentageFormat);

            double falseRatio = stats.GetFalsePositiveRatio(startIndex, endIndex);
            falseTextBox.Text = falseRatio.ToString(PercentageFormat);

            double clicksPerfect = stats.PerfectDetection.GetNumClicks(startIndex, endIndex);
            pNumberTextBox.Text = clicksPerfect.ToString();
            
            double positivesPerfect = stats.PerfectDetection.GetNumDetections(true, startIndex, endIndex);
            pLengthTextBox.Text = (positivesPerfect / clicksPerfect).ToString(DoubleFormat);

            double clicksDetected = stats.Detection.GetNumClicks(startIndex, endIndex);
            clicksDetectedTextBox.Text = clicksDetected.ToString();

            double positivesDetected = stats.Detection.GetNumDetections(true, startIndex, endIndex);
            dLengthTextBox.Text = (positivesDetected / clicksDetected).ToString(DoubleFormat);

            double count = endIndex - startIndex + 1;

            double numPositives = stats.GetNumDetections(true, true, startIndex, endIndex);
            positiveSlice.Value = numPositives / count;

            double numFalsePositives = stats.GetNumDetections(false, true, startIndex, endIndex);
            falseSlice.Value = numFalsePositives / count;

            double numMissedPositives = stats.GetNumDetections(true, false, startIndex, endIndex);
            missedSlice.Value = numMissedPositives / count;

            double numNegatives = stats.GetNumDetections(false, false, startIndex, endIndex);
            negativeSlice.Value = numNegatives / count;

            statisGroupBox.Refresh();
        }

        private void ResetDetection(int startIndex, int endIndex)
        {
            detectionGraph.GraphPane.XAxis.Scale.Min = startIndex;
            detectionGraph.GraphPane.XAxis.Scale.Max = endIndex;
            detectionGraph.GraphPane.YAxis.Scale.Min = DAPNet.Sample.MinValue;
            detectionGraph.GraphPane.YAxis.Scale.Max = DAPNet.Sample.MaxValue;

            clickedCurve.Symbol.Type = displayClickedSymbolsCheckBox.Checked ? ShownSymbol : HiddenSymbol;
            clickedCurve.Color = displayClickedCheckBox.Checked ? ClickedCurveColor : Color.Transparent;
            samplesCurve.Symbol.Type = displaySamplesSymbolsCheckBox.Checked ? ShownSymbol : HiddenSymbol;
            samplesCurve.Color = displaySamplesCheckBox.Checked ? SamplesCurveColor : Color.Transparent;
            clickingCurve.Symbol.Type = displayClickingSymbolsCheckBox.Checked ? ShownSymbol : HiddenSymbol;
            clickingCurve.Color = displayClickingCheckBox.Checked ? ClickingCurveColor : Color.Transparent;
            
            detectionGraph.AxisChange();
            detectionGraph.Refresh();
        }


        private void displayAllButton_Click(object sender, EventArgs e)
        {
            ResetDisplay(0, stats.Count - 1);
            ResetStats(0, stats.Count - 1);
            ResetDetection(0, stats.Count - 1);
        }

        private void displayButton_Click(object sender, EventArgs e)
        {
            int startIndex = 0;
            bool isStartIndexValid = Int32.TryParse(startTextBox.Text, out startIndex);
            startIndex = Math.Max(0, startIndex);
            
            int endIndex = 0;
            bool isEndIndexValid = Int32.TryParse(endTextBox.Text, out endIndex);
            endIndex = Math.Min(stats.Count - 1, endIndex);

            if (isStartIndexValid && isEndIndexValid && startIndex < endIndex)
            {
                ResetDisplay(startIndex, endIndex);
                ResetStats(startIndex, endIndex);
                ResetDetection(startIndex, endIndex);
            }
        }

        private void detectionGraph_ScrollDoneEvent(ZedGraphControl sender, ScrollBar scrollBar, ZoomState oldState, ZoomState newState)
        {
            detectionGraph_ZoomEvent(sender, oldState, newState);
        }

        private void detectionGraph_ZoomEvent(ZedGraphControl sender, ZoomState oldState, ZoomState newState)
        {
            int startIndex = (int)detectionGraph.GraphPane.XAxis.Scale.Min;
            startIndex = Math.Max(0, startIndex);
            
            int endIndex = (int)detectionGraph.GraphPane.XAxis.Scale.Max;
            endIndex = Math.Min(stats.Count - 1, endIndex);

            ResetDisplay(startIndex, endIndex);
            ResetStats(startIndex, endIndex);
            ResetDetection(startIndex, endIndex);
        }

        private void displayCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            int startIndex = (int)detectionGraph.GraphPane.XAxis.Scale.Min;
            int endIndex = (int)detectionGraph.GraphPane.XAxis.Scale.Max;
            
            ResetDisplay(startIndex, endIndex);
            ResetDetection(startIndex, endIndex);
        }


        private LineItem AddSamplesCurve(string label, SampleCollection samples, Color color)
        {
            PointPairList samplePoints = new PointPairList();
            for (int i = 0; i < samples.Count; i++)
            {
                double value = samples[i].Value;
                samplePoints.Add(i, value);
            }

            LineItem samplesCurve = detectionGraph.GraphPane.AddCurve(label, samplePoints, color, SymbolType.None);
            samplesCurve.Line.IsSmooth = true;
            return samplesCurve;
        }

        private LineItem AddDetectionCurve(string label, ClickDetection detection, double positiveValue, double negativeValue, Color color)
        {
            double offset = 0.5;
            PointPairList detectionPoints = new PointPairList();
            for (int i = 0; i < detection.Count; i++)
            {
                double value = detection[i] ? positiveValue : negativeValue;
                detectionPoints.Add(i - offset, value);
            }

            LineItem detectionCurve = detectionGraph.GraphPane.AddCurve(label, detectionPoints, Color.Transparent, SymbolType.None);
            detectionCurve.Line.Fill = new Fill(color);
            detectionCurve.Line.StepType = StepType.ForwardStep;
            return detectionCurve;
        }
    }
}
